package start.demo01.http;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * http工具类
 * post请求头中的数据如果有中文必须进行编码，然后在接口中进行译码，否则中文会出现乱码,所以一般不在请求头放中文
 */
@Slf4j
public class HttpTools {

    private static final String POST = "POST";
    private static final String GET = "GET";

    public static void main(String[] args) throws IOException, URISyntaxException {
        URI uri = new URIBuilder("https://test.mg.tf.cn/opm/healthyCheck").build();
        HttpResponse http = http(uri, "GET", null, null);
//        HttpResponse httpResponse = get(uri);
        String s = dealResponse(http);
        System.out.println(s);
    }

    public static HttpResponse get(URI uri) throws IOException {
        return http(uri, GET, null);
    }

    //post请求获取响应
    public static HttpResponse post(URI uri) throws IOException {
        return http(uri, POST, null);
    }

    /**
     * @param uri
     * @param method 请求方式
     * @param header 请求头
     * @throws IOException
     */
    public static HttpResponse http(URI uri, final String method, Map<String, String> header) throws IOException {
        return http(uri, method, header, null);
    }

    public static HttpResponse http(URI uri, final String method, Map<String, String> header, String requestBody) throws IOException {
        RequestConfig requestConfig = RequestConfig.custom()
                .setSocketTimeout(15000)//获取数据的超时时间
                .setConnectTimeout(10000)//建立连接的超时
                .setConnectionRequestTimeout(10000)//连接池获取到连接的超时时间
                .build();

        HttpClient client = HttpClients.createDefault();
        HttpEntityEnclosingRequestBase http = new HttpEntityEnclosingRequestBase() {
            @Override
            public String getMethod() {
                return method.toUpperCase();
            }
        };
        http.setURI(uri);
        // 组织数据
        StringEntity se;
        if (StringUtils.isNotEmpty(requestBody)) {
            se = new StringEntity(requestBody, Consts.UTF_8);
            //设置编码格式
            se.setContentEncoding(Consts.UTF_8.toString());
            http.setEntity(se);
        }
        http.setConfig(requestConfig);
        //添加header信息
        addHeader(http, header);
        log.info("\n发起http请求:{}", JSON.toJSONString(uri));
        HttpResponse response = client.execute(http);
        return response;
    }

    public static HttpResponse http(String uri, final String method, Map<String, String> header) throws IOException, URISyntaxException {
        return http(new URIBuilder(uri).build(), method, header);
    }

    public static HttpResponse http(String uri, String method, String requestBody) throws URISyntaxException, IOException {
        return http(new URIBuilder(uri).build(), method, null, requestBody);
    }

    public static HttpResponse postByJson(URI uri, Map<String, Object> requestBody) throws IOException {
        return postByJson(uri, requestBody, null);
    }

    public static HttpResponse postByJson(URI uri, String requestBody) throws IOException {
        return postByJson(uri, requestBody, null);
    }

    public static HttpResponse postByJson(String uri, String requestBody) throws IOException, URISyntaxException {
        return postByJson(new URIBuilder(uri).build(), requestBody, null);
    }

    public static HttpResponse postByJson(URI uri, Map<String, Object> requestBody, Map<String, String> header) throws IOException {
        return postByJson(uri, JSON.toJSONString(requestBody), header);
    }

    /**
     * ajax提交
     *
     * @param uri         路径
     * @param requestBody 请求体
     * @param header      请求头
     * @throws IOException
     */
    public static HttpResponse postByJson(URI uri, String requestBody, Map<String, String> header) throws IOException {
        HttpClient client = HttpClients.createDefault();
        HttpPost post = new HttpPost(uri);

        addHeader(post, header);
        //使用addHeader方法添加请求头部,诸如User-Agent, Accept-Encoding等参数.
        post.setHeader("Content-Type", "application/json;charset=UTF-8");
        post.setHeader("conn", "Hello ! this is my HTTP! ~~~~");
        // 组织数据
        if (StringUtils.isNotEmpty(requestBody)) {
            StringEntity se = new StringEntity(requestBody, Consts.UTF_8);
            //设置编码格式
            se.setContentEncoding(Consts.UTF_8.toString());
            //设置数据类型
            //se.setContentType("application/json");
            //对于POST请求,把请求体填充进HttpPost实体.
            post.setEntity(se);
        }
        HttpResponse execute = client.execute(post);
        return execute;
    }

    public static String dealResponse(HttpResponse response) throws IOException {
//        if (response.getStatusLine().getStatusCode() == 200) {
        HttpEntity resEntity = response.getEntity();
        String message = EntityUtils.toString(resEntity, Consts.UTF_8);
        return message;
//        } else {
//            return "请求失败";
//        }
    }

    public static void addHeader(HttpEntityEnclosingRequestBase http, Map<String, String> header) {
        //添加header信息
        if (header != null) {
            Iterator<Map.Entry<String, String>> iterator = header.entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry<String, String> next = iterator.next();
                http.setHeader(next.getKey(), next.getValue());
            }
        }
    }

    //文件上传
    public String postForUpload(String url, Map<String, String> headers, List files, String fileName,
                                Map<String, String> params) {
        CloseableHttpClient client = HttpClients.createDefault();
        HttpPost post = new HttpPost(url);
        if (headers!=null&&!headers.isEmpty()) {
            for (Map.Entry<String, String> entity : headers.entrySet()) {
                post.setHeader(entity.getKey(), entity.getValue());
            }
        }
        try {
            MultipartEntityBuilder builder = MultipartEntityBuilder.create();
            builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
            builder.setCharset(StandardCharsets.UTF_8);
            if (files!=null&&!files.isEmpty()) {
                //上传的文件体
                for (Object file : files) {
                    if (file instanceof File) {
                        builder.addBinaryBody("file", (File) file);
                    }
                    if (file instanceof InputStream) {
                        builder.addBinaryBody("file", (InputStream) file, ContentType.MULTIPART_FORM_DATA, fileName);
                    }
                    if (file instanceof byte[]) {
                        builder.addBinaryBody("file", (byte[]) file, ContentType.MULTIPART_FORM_DATA, fileName);
                    }
                }
            }
            if (params!=null&&!params.isEmpty()) {
                for (Map.Entry<String, String> entity : params.entrySet()) {
                    if (StringUtils.isNotBlank(entity.getValue())) {
                        builder.addTextBody(entity.getKey(), entity.getValue());
                    }
                }
            }
            HttpEntity entity = builder.build();
            post.setEntity(entity);
            HttpResponse response = client.execute(post);

            // 设置连接超时时间
            int timeout = 5000;
            RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(timeout)
                    .setConnectionRequestTimeout(timeout).setSocketTimeout(timeout).build();
            post.setConfig(requestConfig);

            entity = response.getEntity();
            if (null != entity) {
                return EntityUtils.toString(entity, Charset.forName("ISO-8859-1"));
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                client.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}